#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdio.h>
#include "consts.h"
#include "transfer.h"
#include "helper.h"

CLIENT * client_create(char * host)
{
  CLIENT * result = clnt_create(host, PAPER_PROG, FIRST_VERS, "tcp");
  if (result == 0) {
    printf("Unanable to connect to '%s'.\n", host);
    exit(EXIT_FAILURE);
  }
  return result;
}


void print_info()
{
  printf("  Usage:\n");
  printf("    paperclient list   <host>\n");
  printf("    paperclient add    <host> ’<Author Name>’ ’<Paper Title>’ <filename>\n");
  printf("    paperclient detail <host> <number>\n");
  printf("    paperclient fetch  <host> <number>\n");
  printf("\n");
}

void list(char * host_name)
{
  CLIENT * client = client_create(host_name);
  struct paper_info_t * paper_info;

  int i = 0;
  paper_info = get_paper_1(&i, client);
  if (paper_info->error) {
    printf("No papers at server yet.\n");
    clnt_destroy(client);
    return;
  } 
  printf("id author\ttitle\n");
  printf("%d. %s '%s'\n", i, paper_info->author, paper_info->title);

  while (paper_info->next_paper_id != -1) {
    i = paper_info->next_paper_id;
    paper_info = get_paper_1(&i, client);
    if (paper_info->error) {
      printf("Internal error: %s\n", paper_info->error_message);
      clnt_destroy(client);
      return;
    }
    printf("%d. %s '%s'\n", i, paper_info->author, paper_info->title);
  } 
  clnt_destroy(client);
}

void add(char * host_name, char * author, char * title, char * filename)
{
  FILE * file = fopen(filename, "r");
  if (file == 0) {
    printf("Unanable to open file '%s'.", filename);
    return;
  }
  CLIENT * client = client_create(host_name);
  struct paper_info_t paper_info;
  paper_info_create(&paper_info, author, title, filename);
  int * paper_id = paper_add_1(&paper_info, client);
  printf("Paper id: %d\n", *paper_id);

  int size;
  char buffer[BLOCK_SIZE];
  block_t block;
  error_info_t * info;
  while ((size = fread(buffer,1,BLOCK_SIZE,file)) > 0) {
    create_block(&block, *paper_id, buffer, size);
    info = add_block_1(&block, client);
    if (info->error) {
      printf("Internal error: unanable to find paper with id: %d\n", *paper_id);
      exit(1);
    }
  }
  clnt_destroy(client);
  fclose(file);
}


void detail(char * host_name, char * number)
{
  CLIENT * client = client_create(host_name);
  int paper_id = atoi(number);  
  struct paper_info_t * paper_info;
  paper_info = get_paper_1(&paper_id, client);
  if (paper_info->error) {
    printf("ERROR: %s\n", paper_info->error_message);
  } else {
    printf("Id: %d\n", paper_id);
    printf("Title: %s\n", paper_info->title);
    printf("Author(s): %s\n", paper_info->author);
    printf("File name: %s\n", paper_info->file_name);
    printf("\n");
  }
  clnt_destroy(client);
}

void fetch(char * host_name, char * number)
{
  CLIENT * client = client_create(host_name);
  int paper_id = atoi(number);  
  struct paper_info_t * paper_info;
  paper_info = get_paper_1(&paper_id, client);
  if (paper_info->error) {
    printf("ERROR: %s\n", paper_info->error_message);
    return;
  }
  char file_name[MAX_FILE_NAME_LENGTH];
  strncpy(file_name, paper_info->file_name, MAX_FILE_NAME_LENGTH);
  strcat(file_name, DOWNLOAD_FILE_NAME_SUFFIX);
  FILE * file = stdout;
  if (file == 0) {
    printf("Unanable to save file '%s'.\n", file_name);
    clnt_destroy(client);
    return;
  }
  block_request_t request;
  block_t * block;

  int i = 0;
  do {
    create_block_request(&request, paper_id, i++);
    block = get_block_1(&request, client);
    if (block->error) {
      printf("Internal error: unanable too find document by id\n");
      return;
    }
    if (block->size > 0) {
      if (fwrite(block->data,1, block->size,file) < 0) {
        perror("Error in writing\n");
	return;
      }
    }
  } while (block->size > 0);
  fclose(file);
  clnt_destroy(client);
}

int main(int argi, char **argv) 
{
  assert(argi > 0);
  if (argi == 3 && strcmp(argv[1], "list") == 0) {
    list(argv[2]);
  } else if (argi == 6 && strcmp(argv[1], "add") == 0) {
    add(argv[2], argv[3], argv[4], argv[5]);
  } else if (argi == 4 && strcmp(argv[1], "detail") == 0) {
    detail(argv[2], argv[3]);
  } else if (argi == 4 && strcmp(argv[1], "fetch") == 0) {
    fetch(argv[2], argv[3]);
  } else {
    print_info();
  }
  return 0;
}

